package cn.com.taiji.pos.controller;

import cn.com.taiji.model.finals.SessionNames;
import cn.com.taiji.pos.common.util.HttpUtil;
import cn.com.taiji.pos.common.util.MD5;
import cn.com.taiji.pos.common.util.SmallTicketPrinter;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.config.Configs;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.model.GoodsDetail;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.model.builder.AlipayTradePayRequestBuilder;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.model.builder.AlipayTradeQueryRequestBuilder;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.model.result.AlipayF2FPayResult;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.model.result.AlipayF2FQueryResult;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.service.AlipayTradeService;
import cn.com.taiji.pos.common.util.pay.alipay.zhifubao.service.impl.AlipayTradeServiceImpl;
import cn.com.taiji.pos.common.util.pay.wxpay.WXPay;
import cn.com.taiji.pos.common.util.pay.wxpay.WXPayConfigImpl;
import cn.com.taiji.pos.entity.*;
import cn.com.taiji.pos.service.*;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.dreamyoung.mprelation.AutoMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.WebUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/OrderPay")
@Slf4j
public class OrderPayController {

    @Value("${SETTLEMENT_TYPE_ID_YuShouKaJi}")
    private String SETTLEMENT_TYPE_ID_YuShouKaJi;
    @Value("${SETTLEMENT_TYPE_ID_YingShouKaJi}")
    private String SETTLEMENT_TYPE_ID_YingShouKaJi;
    @Value("${SETTLEMENT_TYPE_ID_YingShouCanPiao}")
    private String SETTLEMENT_TYPE_ID_YingShouCanPiao;
    @Value("${MEAL_TIME_ID_quantian}")
    private String MEAL_TIME_ID_quantian;
    @Value("${SETTLEMENT_TYPE_ID_jiesuan}")
    private String SETTLEMENT_TYPE_ID_jiesuan;
    @Value("${PROJECT_CODE}")
    private String PROJECT_CODE;
    @Value("${QR_PASSWORD}")
    private String QR_PASSWORD;
    @Value("${isCupPrinte}")
    private boolean cupPrinte;
    @Value("${isPrinte}")
    private boolean printe;
    @Value("${canteen_allowance}")
    private boolean canteenAllowance;
    @Value("${PAY_RESULT_Url}")
    private String PAY_RESULT_Url;
    @Autowired
    private ISystemPosMachineService systemPosMachineService;
    @Autowired
    private IConfigMealTimeService configMealTimeService;
    @Autowired
    private ITradeAccountConsumptionFlowService tradeAccountConsumptionFlowService;
    @Autowired
    private ITradeConsumptionDetailService tradeConsumptionDetailService;
    @Autowired
    private ITradeConsumptionMainService tradeConsumptionMainService;
    @Autowired
    private IMenuFoodPriceService menuFoodPriceService;
    @Autowired
    private ICardInfoService cardInfoService;
    @Autowired
    private ICardAccountService cardAccountService;
    @Autowired
    private ICardCustomerTypeService cardCustomerTypeService;
    @Autowired
    private ICardCustomerService customerService;
    @Autowired
    private AutoMapper autoMapper;
    @Autowired
    public SmallTicketPrinter smallTicketPrinter;
    @Autowired
    private IMemberAllowanceUseHistoryService memberAllowanceUseHistoryService;
    @Autowired
    private IConfigBusinessTypeService configBusinessTypeService;
    @Autowired
    private ISystemPrinterService systemPrinterService;

    static {
        Configs.init("classpath:config/zfbinfo.properties");
    }

    private static AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
    private static HashMap<String, String> flowNoMap = new HashMap<>();

    /**
     * 现金支付
     *
     * @param data
     * @param model
     * @param request
     * @param response
     */
    @RequestMapping(value = "CashPay", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public String cashSettlement(@RequestBody JSONObject data, Model model, HttpServletRequest request, HttpServletResponse response) {
        SystemAclUser user = (SystemAclUser) WebUtils.getSessionAttribute(request, SessionNames.LOGIN_USER);
        String consumptionAmount = data.getString("consumptionAmount");//消费
        String actualAmount = data.getString("actualAmount");//实收
        String changeAmount = data.getString("changeAmount");//找零
        String physicalCode = data.getString("physicalCode");
        SystemPosMachine systemPosMachine = systemPosMachineService.findByPhysicalCode(physicalCode);
        if (systemPosMachine == null) {
            model.addAttribute("result", "fail");
            model.addAttribute("message", "pos机不存在");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        systemPosMachine = autoMapper.mapperEntity(systemPosMachine);
        SystemPrinter systemPrinter = systemPosMachine.getReceiptPrinter();
        Boolean print = data.getObject("print", Boolean.class);//是否打印
        if (print == null) {
            print = printe;
        }
        //清空上次订单
        flowNoMap.put(physicalCode, "");
        String canci = data.getString("canci");
        List<ItemS> itemsList = JSONObject.parseArray(data.getJSONArray("items").toString(), ItemS.class);
        if (!StringUtils.hasText(actualAmount)) {
            model.addAttribute("result", "fail");
            model.addAttribute("message", "实收金额不能为空");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        } else if (Double.parseDouble(actualAmount) < 0 || Double.parseDouble(changeAmount) < 0) {
            model.addAttribute("result", "fail");
            model.addAttribute("message", "实收金额与消费金额不符，请重新核对!");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        TradeAccountConsumptionFlow tradeAccountConsumptionFlow = new TradeAccountConsumptionFlow();
        tradeAccountConsumptionFlow.setRestaurantId(systemPosMachine.getRestaurantId());
        tradeAccountConsumptionFlow.setPosMachineId(systemPosMachine.getId());
        tradeAccountConsumptionFlow.setStickerPrinter(systemPosMachine.getStickerPrinter());
        tradeAccountConsumptionFlow.setQuantity(itemsList.stream().mapToDouble(ItemS::getCount).sum());
        ConfigMealTime configMealTime = configMealTimeService.findByName(canci);
        if (configMealTime != null) {
            tradeAccountConsumptionFlow.setMealTimeId(configMealTime.getId());
        }
        tradeAccountConsumptionFlow.setOperateType(0);
        tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_jiesuan);

        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyMMddHHmmss");
        tradeAccountConsumptionFlow.setFlowNo(PROJECT_CODE + "-XF" + df.format(LocalDateTime.now()) + UUID.randomUUID().toString().substring(0, 4));
        //记录订单号
        flowNoMap.put(physicalCode, tradeAccountConsumptionFlow.getFlowNo());
        log.info(tradeAccountConsumptionFlow.getFlowNo());
        tradeAccountConsumptionFlow.setIsPay("0");
        tradeAccountConsumptionFlow.setCreatorId(user.getId());
        tradeAccountConsumptionFlow.setCreatorName(user.getName());
        tradeAccountConsumptionFlow.setBeforeAmount(new BigDecimal(0));
        tradeAccountConsumptionFlow.setActualAmount(Double.valueOf(consumptionAmount));
        tradeAccountConsumptionFlow.setAfterAmount(new BigDecimal(0));
        tradeAccountConsumptionFlow.setReasonId("现金支付");
        tradeAccountConsumptionFlow.setCreateTime(LocalDateTime.now());
        tradeAccountConsumptionFlow.setIsOver("1");//已支付
        tradeAccountConsumptionFlow.setTableNo(new Double(Math.random() * 900000 + 100000).intValue() + "");
        tradeAccountConsumptionFlowService.save(tradeAccountConsumptionFlow);
        insertInto(itemsList, tradeAccountConsumptionFlow, user, 1.0);
        //更新pos机金额v
        systemPosMachineService.updateMoney(systemPosMachine, consumptionAmount);
        if (print && systemPrinter != null) {
            //打印小票
            orderReceiptPrint(itemsList, tradeAccountConsumptionFlow, response, systemPrinter);
        }
        model.addAttribute("result", "success");
        model.addAttribute("message", "支付成功");
        model.addAttribute("money", systemPosMachine.getMoney());
        model.addAttribute("changeAmount", changeAmount);
        return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
    }

    /**
     * 刷卡支付
     *
     * @param data
     * @param model
     * @param request
     * @param response
     */
    @RequestMapping(value = "cardPay", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public String cardPay(@RequestBody JSONObject data, Model model, HttpServletRequest request, HttpServletResponse response) {
        boolean flag = false;
        SystemAclUser user = (SystemAclUser) WebUtils.getSessionAttribute(request, SessionNames.LOGIN_USER);
        model.addAttribute("result", "fail");
        String amount = data.getString("amount");//金额
        String cardCode = data.getString("cardCode");//卡片编号
        String physicalCode = data.getString("physicalCode");
        SystemPosMachine systemPosMachine = systemPosMachineService.findByPhysicalCode(physicalCode);
        if (systemPosMachine == null) {
            model.addAttribute("result", "fail");
            model.addAttribute("message", "pos机不存在");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        systemPosMachine = autoMapper.mapperEntity(systemPosMachine);
        SystemPrinter systemPrinter = systemPosMachine.getReceiptPrinter();
//        String tableNo = data.getString("tableNo");
        Boolean print = data.getObject("print", Boolean.class);//是否打印
        if (print == null) {
            print = printe;
        }
        Double discountAmount = 0.0;
        Double minimumConsumption = 0.0;

        //清空上次订单

        flowNoMap.put(physicalCode, "");
        String canci = data.getString("canci");//餐次
        List<ItemS> itemsList = JSONObject.parseArray(data.getJSONArray("items").toString(), ItemS.class);
        double chajia = 0.00;
        double balance = 0.00;
        double tzBalance = 0.00;
        if (!StringUtils.hasText(amount) || Double.parseDouble(amount) < 0) {
            model.addAttribute("message", "金额不能为空");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        List<CardAccount> cardAccountListBase = new ArrayList<>();
        CardInfo cardInfo = null;
        String customerNo = "";
        if (cardCode.contains("&")) {
            //虚拟二维码支付
            String[] split = cardCode.split("&");
            if (split.length != 4) {
                model.addAttribute("message", "二维码无效");
                return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
            } else if (LocalDateTime.now().isAfter(LocalDateTime.parse(split[1], DateTimeFormatter.ofPattern("yyMMddHHmmss")).plusMinutes(2))) {
                model.addAttribute("message", "二维码已过期");
                return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
            } else if (split[0].equals(MD5.MD5Encode(split[3] + split[2] + split[1]).toUpperCase())) {
                //验证通过
                customerNo = split[3];
                cardAccountListBase = cardAccountService.findCardAccountList2(customerService.query().eq("STATUS", 0).eq("CUSTOMER_NO", split[3]).list().get(0).getId());
            }
        } else {
            cardInfo = cardInfoService.findByCardCode(cardCode);
            if (cardInfo == null) {
                model.addAttribute("message", "该卡片未关联账户");
                return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
            }
            cardAccountListBase = cardAccountService.findCardAccountList2(cardInfo.getCustomerId());
        }
        List<CardAccount> cardAccountList = new ArrayList<>();
        for (CardAccount cardAccount : cardAccountListBase) {
            if (cardAccount.getEffectDate() == null || cardAccount.getEffectDate().isAfter(LocalDate.now())) {
                cardAccountList.add(cardAccount);
            }
        }

        //查询账户
        if (cardAccountList.size() == 0) {
            model.addAttribute("message", "本次交易失败,没有可用的账户");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }

        cardAccountList = autoMapper.mapperEntityList(cardAccountList);
        TradeAccountConsumptionFlow tradeAccountConsumptionFlow = new TradeAccountConsumptionFlow();
        tradeAccountConsumptionFlow.setStickerPrinter(systemPosMachine.getStickerPrinter());
        tradeAccountConsumptionFlow.setTableNo(new Double(Math.random() * 900000 + 100000).intValue() + "");
        tradeAccountConsumptionFlow.setRestaurantId(systemPosMachine.getRestaurantId());
        tradeAccountConsumptionFlow.setPosMachineId(systemPosMachine.getId());
        tradeAccountConsumptionFlow.setQuantity(itemsList.stream().mapToDouble(ItemS::getCount).sum());
        ConfigMealTime configMealTime = configMealTimeService.findByName(canci);
        if (configMealTime != null) {
            tradeAccountConsumptionFlow.setMealTimeId(configMealTime.getId());
            tradeAccountConsumptionFlow.setMealCode(configMealTime.getCode());
        }
        tradeAccountConsumptionFlow.setOperateType(0);
        //查询优惠信息
        CardCustomer cardCustomer = customerService.getById(cardAccountList.get(0).getCustomerId());
        CardCustomerType customerType = cardCustomerTypeService.getById(cardCustomer.getCustomerTypeId());
        MemberAllowanceUseHistory memberAllowanceUseHistory = null;
        if (!"canteen".equals(data.getString("type")) || canteenAllowance) {
            if (customerType.getMorningAllowance() > 0 || customerType.getAfternoonAllowance() > 0 || customerType.getEveningAllowance() > 0) {
                //账户类型可优惠
                QueryWrapper<MemberAllowanceUseHistory> memberAllowanceUseHistoryQueryWrapper = new QueryWrapper<>();
                memberAllowanceUseHistoryQueryWrapper.eq("member_id", cardCustomer.getId());
                memberAllowanceUseHistoryQueryWrapper.eq("meal_code", configMealTime.getCode());
                memberAllowanceUseHistoryQueryWrapper.eq("use_time", LocalDate.now());
                memberAllowanceUseHistory = memberAllowanceUseHistoryService.getOne(memberAllowanceUseHistoryQueryWrapper, false);
                Double totalAmount = Double.valueOf(amount);
                switch (configMealTime.getCode()) {
                    case "01":
                        if (totalAmount > customerType.getMorningMinimum()) {
                            tradeAccountConsumptionFlow.setMaxAllowance(customerType.getMorningAllowance());
                            if (memberAllowanceUseHistory == null) {
                                discountAmount = totalAmount <= customerType.getMorningAllowance() ? totalAmount : customerType.getMorningAllowance();
                            } else {
                                discountAmount = totalAmount <= memberAllowanceUseHistory.getAllowanceAmount() ? totalAmount : memberAllowanceUseHistory.getAllowanceAmount();
                            }
                        }
                        break;
                    case "02":
                        if (totalAmount > customerType.getAfternoonMinimum()) {
                            tradeAccountConsumptionFlow.setMaxAllowance(customerType.getAfternoonAllowance());
                            if (memberAllowanceUseHistory == null) {

                                discountAmount = totalAmount <= customerType.getAfternoonAllowance() ? totalAmount : customerType.getAfternoonAllowance();
                            } else {
                                discountAmount = totalAmount <= memberAllowanceUseHistory.getAllowanceAmount() ? totalAmount : memberAllowanceUseHistory.getAllowanceAmount();
                            }
                        }
                        break;
                    case "03":
                        if (totalAmount > customerType.getEveningMinimum()) {
                            tradeAccountConsumptionFlow.setMaxAllowance(customerType.getEveningAllowance());
                            if (memberAllowanceUseHistory == null) {
                                discountAmount = totalAmount <= customerType.getEveningAllowance() ? totalAmount : customerType.getEveningAllowance();
                            } else {
                                discountAmount = totalAmount <= memberAllowanceUseHistory.getAllowanceAmount() ? totalAmount : memberAllowanceUseHistory.getAllowanceAmount();
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
            if (discountAmount > 0) {
                amount = Double.parseDouble(amount) - discountAmount + "";
            }
        }
        List<CardAccount> bzCardAccountList = cardAccountList.stream().filter(i -> "01".equals(i.getAccountType().getCode())).collect(Collectors.toList());
        List<CardAccount> czCardAccountList = cardAccountList.stream().filter(i -> "04".equals(i.getAccountType().getCode())).collect(Collectors.toList());
        CardAccount payCardAccount = null;
        if (bzCardAccountList.size() > 0) {
            CardAccount bzCardAccount = bzCardAccountList.get(0);
            if (bzCardAccount.getAmount().doubleValue() >= Double.parseDouble(amount)) {
                //补助卡支付
                payCardAccount = bzCardAccount;
            } else if (czCardAccountList.size() > 0) {
                CardAccount czCardAccount = czCardAccountList.get(0);
                if ((bzCardAccount.getAmount().doubleValue() + czCardAccount.getAmount().doubleValue()) >= Double.parseDouble(amount) && bzCardAccount.getAmount().doubleValue() > 0.0) {
                    //混合支付
                    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyMMddHHmmss");
                    tradeAccountConsumptionFlow.setFlowNo(PROJECT_CODE + "-XF" + df.format(LocalDateTime.now()) + UUID.randomUUID().toString().substring(0, 4));
                    //记录订单号
                    flowNoMap.put(physicalCode, tradeAccountConsumptionFlow.getFlowNo());
                    log.info(tradeAccountConsumptionFlow.getFlowNo());
                    tradeAccountConsumptionFlow.setCustomerId(czCardAccount.getCustomerId());
                    if (cardInfo != null) {
                        tradeAccountConsumptionFlow.setCardId(cardInfo.getId());
                    }
                    tradeAccountConsumptionFlow.setActualAmount(Double.valueOf(amount));//实扣金额
                    tradeAccountConsumptionFlow.setDiscountAmount(discountAmount);//折扣金额，待确认
                    tradeAccountConsumptionFlow.setTimes(0);
                    tradeAccountConsumptionFlow.setReasonId("刷卡消费");
                    tradeAccountConsumptionFlow.setIsPay("0");//是否开具发票
                    tradeAccountConsumptionFlow.setCreatorId(user.getId());
                    tradeAccountConsumptionFlow.setCreatorName(user.getName());
                    tradeAccountConsumptionFlow.setIsOver("0");//未支付
                    tradeAccountConsumptionFlow.setCreateTime(LocalDateTime.now());
                    tradeAccountConsumptionFlow.setCustomerName(cardCustomer.getName());
                    Double bzpayoutRatio = bzCardAccount.getAmount().doubleValue() / Double.parseDouble(amount);
                    Double czpayoutRatio = (Double.parseDouble(amount) - bzCardAccount.getAmount().doubleValue()) / Double.parseDouble(amount);
                    TradeAccountConsumptionFlow bzConsumptionFlow = new TradeAccountConsumptionFlow();
                    TradeAccountConsumptionFlow czConsumptionFlow = new TradeAccountConsumptionFlow();
                    BeanUtils.copyProperties(tradeAccountConsumptionFlow, bzConsumptionFlow);
                    BeanUtils.copyProperties(tradeAccountConsumptionFlow, czConsumptionFlow);
                    //补助卡流水
                    bzConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YingShouKaJi);
                    bzConsumptionFlow.setAccountId(bzCardAccount.getId());
                    bzConsumptionFlow.setBeforeAmount(bzCardAccount.getAmount());//扣前金额
                    bzConsumptionFlow.setActualAmount(bzCardAccount.getAmount().doubleValue());//实扣金额
                    bzConsumptionFlow.setAfterAmount(BigDecimal.ZERO);//扣后金额
                    bzConsumptionFlow.setDiscountAmount(discountAmount * bzpayoutRatio);//折扣金额，待确认
                    bzConsumptionFlow.setBeforeTimes(bzCardAccount.getTimes());//操作前次数
                    bzConsumptionFlow.setAfterTimes(bzCardAccount.getTimes());//操作后次数
                    //储值卡流水
                    czConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YuShouKaJi);
                    czConsumptionFlow.setAccountId(czCardAccount.getId());
                    czConsumptionFlow.setBeforeAmount(czCardAccount.getAmount());//扣前金额
                    czConsumptionFlow.setActualAmount(Double.parseDouble(amount) * czpayoutRatio);//实扣金额
                    czConsumptionFlow.setAfterAmount(czCardAccount.getAmount().subtract(new BigDecimal(czConsumptionFlow.getActualAmount())));//扣后金额
                    czConsumptionFlow.setDiscountAmount(discountAmount * czpayoutRatio);//折扣金额，待确认
                    czConsumptionFlow.setBeforeTimes(czCardAccount.getTimes());//操作前次数
                    czConsumptionFlow.setAfterTimes(czCardAccount.getTimes());//操作后次数
                    tradeAccountConsumptionFlow.setBeforeAmount(czConsumptionFlow.getAfterAmount().add(new BigDecimal(amount)));//扣前金额
                    tradeAccountConsumptionFlow.setAfterAmount(czConsumptionFlow.getAfterAmount());
                    tradeAccountConsumptionFlowService.save(bzConsumptionFlow);
                    tradeAccountConsumptionFlowService.save(czConsumptionFlow);
                    insertInto(itemsList, bzConsumptionFlow, user, bzpayoutRatio);
                    insertInto(itemsList, czConsumptionFlow, user, czpayoutRatio);
                    bzCardAccount.setAmount(bzConsumptionFlow.getAfterAmount());
                    czCardAccount.setAmount(czConsumptionFlow.getAfterAmount());
                    cardAccountService.updateById(bzCardAccount);
                    bzConsumptionFlow.setIsOver("1");//已支付
                    tradeAccountConsumptionFlowService.updateById(bzConsumptionFlow);
                    cardAccountService.updateById(czCardAccount);
                    czConsumptionFlow.setIsOver("1");//已支付
                    tradeAccountConsumptionFlowService.updateById(czConsumptionFlow);
                    if (cupPrinte && tradeAccountConsumptionFlow.getStickerPrinter() != null) {
                        smallTicketPrinter.cupStickersPrint(itemsList, tradeAccountConsumptionFlow);
                    }
                    flag = true;
                } else if ((bzCardAccount.getAmount().doubleValue() + czCardAccount.getAmount().doubleValue()) >= Double.parseDouble(amount)) {
                    payCardAccount = czCardAccount;
                } else {
                    chajia = Double.parseDouble(amount) - (bzCardAccount.getAmount().doubleValue() + czCardAccount.getAmount().doubleValue());
                }
            }
        } else if (czCardAccountList.size() > 0) {
            CardAccount czCardAccount = czCardAccountList.get(0);
            if (czCardAccount.getAmount().doubleValue() >= Double.parseDouble(amount)) {
                //储值卡支付
                payCardAccount = czCardAccount;
            } else {
                chajia = Double.parseDouble(amount) - czCardAccount.getAmount().doubleValue();
            }

        }
        if (payCardAccount != null) {
            balance = payCardAccount.getAmount().doubleValue() - Double.parseDouble(amount);
            model.addAttribute("balance", "账户剩余金额" + balance);
            //储值账户有钱并且够用
            if ("储值账户".equals(payCardAccount.getSddName())) {
                tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YuShouKaJi);
            } else if ("补助账户".equals(payCardAccount.getSddName())) {
                tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YingShouKaJi);
            } else if ("餐票账户".equals(payCardAccount.getSddName())) {
                tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YingShouCanPiao);
            }
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyMMddHHmmss");
            tradeAccountConsumptionFlow.setFlowNo(PROJECT_CODE + "-XF" + df.format(LocalDateTime.now()) + UUID.randomUUID().toString().substring(0, 4));
            //记录订单号
            flowNoMap.put(physicalCode, tradeAccountConsumptionFlow.getFlowNo());
            log.info(tradeAccountConsumptionFlow.getFlowNo());
            tradeAccountConsumptionFlow.setCustomerId(payCardAccount.getCustomerId());
            if (cardInfo != null) {
                tradeAccountConsumptionFlow.setCardId(cardInfo.getId());
            }
            tradeAccountConsumptionFlow.setAccountId(payCardAccount.getId());
            tradeAccountConsumptionFlow.setBeforeAmount(payCardAccount.getAmount());//扣前金额
            tradeAccountConsumptionFlow.setActualAmount(Double.valueOf(amount));//实扣金额
            tradeAccountConsumptionFlow.setAfterAmount(payCardAccount.getAmount().subtract(new BigDecimal(amount)));//扣后金额
            tradeAccountConsumptionFlow.setDiscountAmount(discountAmount);//折扣金额，待确认
            tradeAccountConsumptionFlow.setBeforeTimes(payCardAccount.getTimes());//操作前次数
            tradeAccountConsumptionFlow.setTimes(0);
            tradeAccountConsumptionFlow.setAfterTimes(payCardAccount.getTimes());//操作后次数
            tradeAccountConsumptionFlow.setReasonId("刷卡消费");
            tradeAccountConsumptionFlow.setIsPay("0");//是否开具发票
            tradeAccountConsumptionFlow.setCreatorId(user.getId());
            tradeAccountConsumptionFlow.setCreatorName(user.getName());
            tradeAccountConsumptionFlow.setIsOver("0");//未支付
            tradeAccountConsumptionFlow.setCreateTime(LocalDateTime.now());
            tradeAccountConsumptionFlow.setCustomerName(cardCustomer.getName());
            payCardAccount.setAmount(tradeAccountConsumptionFlow.getAfterAmount());
            tradeAccountConsumptionFlowService.saveOrUpdate(tradeAccountConsumptionFlow);
            insertInto(itemsList, tradeAccountConsumptionFlow, user, 1.0);
            if (cardAccountService.updateById(payCardAccount)) {
                tradeAccountConsumptionFlow.setIsOver("1");//已支付
                tradeAccountConsumptionFlowService.updateById(tradeAccountConsumptionFlow);
            }
            flag = true;
        }

//        for (CardAccount cardAccount : cardAccountList) {
//            if (cardAccount.getEffectDate() != null) {
//                if (cardAccount.getEffectDate().isBefore(LocalDate.now())) {
//                    continue;
//                }
//            }
//            if (cardAccount.getAmount().compareTo(BigDecimal.ZERO) > 0) {
//                //账户有钱
//                if (cardAccount.getAmount().doubleValue() >= Double.parseDouble(amount)) {
//                    balance = cardAccount.getAmount().doubleValue() - Double.parseDouble(amount);
//                    model.addAttribute("balance", "账户剩余金额" + balance);
//                    //储值账户有钱并且够用
//                    if ("储值账户".equals(cardAccount.getSddName())) {
//                        tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YuShouKaJi);
//                    } else if ("补助账户".equals(cardAccount.getSddName())) {
//                        tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YingShouKaJi);
//                    } else if ("餐票账户".equals(cardAccount.getSddName())) {
//                        tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YingShouCanPiao);
//                    }
//                    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyMMddHHmmss");
//                    tradeAccountConsumptionFlow.setFlowNo(PROJECT_CODE + "-XF" + df.format(LocalDateTime.now()) + UUID.randomUUID().toString().substring(0, 4));
//                    //记录订单号
//                    WebUtils.setSessionAttribute(request, physicalCode, tradeAccountConsumptionFlow.getFlowNo());
//                    tradeAccountConsumptionFlow.setCustomerId(cardAccount.getCustomerId());
//                    if (cardInfo != null) {
//                        tradeAccountConsumptionFlow.setCardId(cardInfo.getId());
//                    }
//                    tradeAccountConsumptionFlow.setAccountId(cardAccount.getId());
//                    tradeAccountConsumptionFlow.setBeforeAmount(cardAccount.getAmount());//扣前金额
//                    tradeAccountConsumptionFlow.setActualAmount(Double.valueOf(amount));//实扣金额
//                    tradeAccountConsumptionFlow.setAfterAmount(cardAccount.getAmount().subtract(new BigDecimal(amount)));//扣后金额
//                    tradeAccountConsumptionFlow.setDiscountAmount(discountAmount);//折扣金额，待确认
//                    tradeAccountConsumptionFlow.setBeforeTimes(cardAccount.getTimes());//操作前次数
//                    tradeAccountConsumptionFlow.setTimes(0);
//                    tradeAccountConsumptionFlow.setAfterTimes(cardAccount.getTimes());//操作后次数
//                    tradeAccountConsumptionFlow.setReasonId("刷卡消费");
//                    tradeAccountConsumptionFlow.setIsPay("0");//是否开具发票
//                    tradeAccountConsumptionFlow.setCreatorId(user.getId());
//                    tradeAccountConsumptionFlow.setCreatorName(user.getName());
//                    tradeAccountConsumptionFlow.setIsOver("0");//未支付
//                    tradeAccountConsumptionFlow.setCreateTime(LocalDateTime.now());
//                    tradeAccountConsumptionFlow.setCustomerName(cardCustomer.getName());
//                    cardAccount.setAmount(tradeAccountConsumptionFlow.getAfterAmount());
//                    tradeAccountConsumptionFlowService.saveOrUpdate(tradeAccountConsumptionFlow);
//                    insertInto(itemsList, tradeAccountConsumptionFlow, user);
//                    if (cardAccountService.updateById(cardAccount)) {
//                        tradeAccountConsumptionFlow.setIsOver("1");//已支付
//                        tradeAccountConsumptionFlowService.updateById(tradeAccountConsumptionFlow);
//                    }
//                    flag = true;
//                    break;
//                }
//                chajia = Double.parseDouble(amount) - cardAccount.getAmount().doubleValue();
//
//            }
//        }
        CardCustomerType cardCustomerType = cardCustomerTypeService.getById(cardAccountList.get(0).getCctID());
        //透支情况
        if (!flag) {
            if ("1".equals(cardCustomerType.getIsOverdraft())) {
                //可以透支
                int i = 1;
                for (CardAccount cardAccount : cardAccountList) {
                    i++;
                    if (!"按次账户".equals(cardAccount.getSddName())) {
                        if (cardAccount.getEffectDate() != null && cardAccount.getEffectDate().getYear() != 1) {
                            if (cardAccount.getEffectDate().isBefore(LocalDate.now())) {
                                continue;
                            }
                        }
                        if (cardAccount.getAmount().doubleValue() - Double.parseDouble(amount) <= cardCustomerType.getOverdraft().doubleValue()) {
                            tzBalance = cardCustomerType.getOverdraft().doubleValue() - (cardAccount.getAmount().doubleValue() - Double.parseDouble(amount));
                            model.addAttribute("balance", "账户剩余可透支金额" + tzBalance);
                            if ("储值账户".equals(cardAccount.getSddName())) {
                                tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YuShouKaJi);
                            } else if ("补助账户".equals(cardAccount.getSddName())) {
                                tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YingShouKaJi);
                            } else if ("餐票账户".equals(cardAccount.getSddName())) {
                                tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_YingShouCanPiao);
                            }
                            tradeAccountConsumptionFlow.setCustomerId(cardAccount.getCustomerId());
                            tradeAccountConsumptionFlow.setAccountId(cardAccount.getId());
                            if (cardInfo != null) {
                                tradeAccountConsumptionFlow.setCardId(cardInfo.getId());
                            }
                            tradeAccountConsumptionFlow.setBeforeAmount(cardAccount.getAmount());//扣前金额
                            tradeAccountConsumptionFlow.setActualAmount(Double.valueOf(amount));//实扣金额
                            tradeAccountConsumptionFlow.setAfterAmount(cardAccount.getAmount().subtract(new BigDecimal(amount)));//扣后金额
                            tradeAccountConsumptionFlow.setDiscountAmount(discountAmount);//折扣金额，待确认
                            tradeAccountConsumptionFlow.setBeforeTimes(cardAccount.getTimes());//操作前次数
                            tradeAccountConsumptionFlow.setTimes(0);
                            tradeAccountConsumptionFlow.setAfterTimes(cardAccount.getTimes());//操作后次数
                            tradeAccountConsumptionFlow.setReasonId("刷卡消费");
                            tradeAccountConsumptionFlow.setIsPay("0");//是否开具发票
                            tradeAccountConsumptionFlow.setCreatorId(user.getId());
                            tradeAccountConsumptionFlow.setCreatorName(user.getName());
                            tradeAccountConsumptionFlow.setIsOver("0");//未支付
                            tradeAccountConsumptionFlow.setCreateTime(LocalDateTime.now());
                            cardAccount.setAmount(tradeAccountConsumptionFlow.getAfterAmount());
                            tradeAccountConsumptionFlowService.save(tradeAccountConsumptionFlow);
                            insertInto(itemsList, tradeAccountConsumptionFlow, user, 1.0);
                            if (cardAccountService.updateById(cardAccount)) {
                                tradeAccountConsumptionFlow.setIsOver("1");//已支付
                                tradeAccountConsumptionFlowService.updateById(tradeAccountConsumptionFlow);
                            }
                            break;
                        } else if (i == cardAccountList.size()) {
                            chajia = cardAccount.getAmount().doubleValue() - Double.parseDouble(amount) - cardCustomerType.getOverdraft().doubleValue();
                            System.out.println("++++++++++++++++++++++++++++++++++++++支付失败+++++++++++++++++++++fail+交易失败,余额不足并且不可透支");
                            model.addAttribute("message", "交易失败,余额不足并且不可透支");
                            model.addAttribute("chajia", chajia);
                            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
                        }
                    }
                }

            } else {
                System.out.println("++++++++++++++++++++++++++++++++++++++支付失败+++++++++++++++++++++fail+余额不足");
                model.addAttribute("message", "余额不足,当前余额:" + chajia);
                model.addAttribute("chajia", chajia);
                return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
            }
        }
        if (cardInfo == null && StringUtils.hasText(PAY_RESULT_Url)) {
            //发送扫码通知
            Map<String, String> params = new HashMap<>();
            params.put("customerNo", customerNo);
            params.put("message", amount);
            HttpUtil.sendToPostWithParameter(PAY_RESULT_Url, params);
        }
        if (print && systemPrinter != null) {
            //打印小票
            orderReceiptPrint(itemsList, tradeAccountConsumptionFlow, response, systemPrinter);
        }

        model.addAttribute("result", "success");
        model.addAttribute("message", "支付成功");
        model.addAttribute("amount", amount);
        model.addAttribute("cardCustomerType", customerType.getName());
        model.addAttribute("discountAmount", discountAmount);
        model.addAttribute("beforeAmount", tradeAccountConsumptionFlow.getBeforeAmount());
        model.addAttribute("afterAmount", tradeAccountConsumptionFlow.getAfterAmount());
        model.addAttribute("customerName", cardCustomer.getName());
        model.addAttribute("customerNo", cardCustomer.getCustomerNo());
        return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
    }


    /**
     * 刷卡/现金订单查询
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/cardORCashPayQuery.do", method = RequestMethod.POST)
    public String cardORCashPayQuery(Model model, HttpServletResponse response, HttpServletRequest request) {
        model.addAttribute("result", "fail");
        String physicalCode = request.getParameter("physicalCode");
        String outTradeNo = flowNoMap.get(physicalCode) == null ? "" : flowNoMap.get(physicalCode);
        List<TradeAccountConsumptionFlow> list = tradeAccountConsumptionFlowService.query()
                .eq("FLOW_NO", outTradeNo)
                .eq("IS_OVER", "1")
                .ge("CREATE_TIME", LocalDateTime.now().minusMinutes(1)).list();
        if (list.size() > 0) {
            //有已支付流水单
            model.addAttribute("result", "success");
            model.addAttribute("message", "支付成功");
        } else {
            model.addAttribute("message", "支付失败请重试");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
    }


    /**
     * 支付宝支付
     *
     * @param data
     * @param model
     * @param request
     * @param response
     */
    @RequestMapping(value = "/alipay.do", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public String alipay(@RequestBody JSONObject data, Model model, HttpServletResponse response, HttpServletRequest request) {
        model.addAttribute("result", "fail");
        SystemAclUser user = (SystemAclUser) WebUtils.getSessionAttribute(request, SessionNames.LOGIN_USER);
        System.err.println("支付宝支付开始=====");
        String authCode = data.getString("auth_code");
        String totalAmount = data.getString("amount");// TODO正式用
        String physicalCode = data.getString("physicalCode");
        SystemPosMachine systemPosMachine = systemPosMachineService.findByPhysicalCode(physicalCode);
        if (systemPosMachine == null) {
            model.addAttribute("result", "fail");
            model.addAttribute("message", "pos机不存在");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        systemPosMachine = autoMapper.mapperEntity(systemPosMachine);
        SystemPrinter systemPrinter = systemPosMachine.getReceiptPrinter();
//        String tableNo = data.getString("tableNo");
        Boolean print = data.getObject("print", Boolean.class);//是否打印
        if (print == null) {
            print = printe;
        }
        //清空上次订单

        flowNoMap.put(physicalCode, "");
        String canci = data.getString("canci");//餐次
        List<ItemS> itemsList = JSONObject.parseArray(data.getJSONArray("itemsList").toString(), ItemS.class);
        //生成消费流水
        TradeAccountConsumptionFlow tradeAccountConsumptionFlow = new TradeAccountConsumptionFlow();
        tradeAccountConsumptionFlow.setQuantity(itemsList.stream().mapToDouble(ItemS::getCount).sum());
        tradeAccountConsumptionFlow.setStickerPrinter(systemPosMachine.getStickerPrinter());
        ConfigMealTime configMealTime = configMealTimeService.findByName(canci);
        tradeAccountConsumptionFlow.setRestaurantId(systemPosMachine.getRestaurantId());
        tradeAccountConsumptionFlow.setPosMachineId(systemPosMachine.getId());
        if (configMealTime != null) {
            tradeAccountConsumptionFlow.setMealTimeId(configMealTime.getId());
        }
        tradeAccountConsumptionFlow.setOperateType(0);
        tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_jiesuan);

        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyMMddHHmmss");
        tradeAccountConsumptionFlow.setFlowNo(PROJECT_CODE + "-XF" + df.format(LocalDateTime.now()) + UUID.randomUUID().toString().substring(0, 4));
        //记录订单号
        flowNoMap.put(physicalCode, tradeAccountConsumptionFlow.getFlowNo());
        log.info(tradeAccountConsumptionFlow.getFlowNo());
        tradeAccountConsumptionFlow.setIsPay("0");
        tradeAccountConsumptionFlow.setTableNo(new Double(Math.random() * 900000 + 100000).intValue() + "");
        tradeAccountConsumptionFlow.setCreatorId(user.getId());
        tradeAccountConsumptionFlow.setCreatorName(user.getName());
        tradeAccountConsumptionFlow.setBeforeAmount(new BigDecimal(0));
        tradeAccountConsumptionFlow.setActualAmount(Double.valueOf(totalAmount));
        tradeAccountConsumptionFlow.setAfterAmount(new BigDecimal(0));
        tradeAccountConsumptionFlow.setReasonId("支付宝支付");
        tradeAccountConsumptionFlow.setCreateTime(LocalDateTime.now());
        tradeAccountConsumptionFlow.setIsOver("0");//未支付
        //存储流水
        tradeAccountConsumptionFlowService.save(tradeAccountConsumptionFlow);
        //订单号
        String flowNo = tradeAccountConsumptionFlow.getFlowNo();

        // 商品明细列表，需填写购买商品详细信息，
        List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
        // 创建一个商品信息，参数含义分别为商品id（使用国标）、名称、单价（单位为分）、数量，如果需要添加商品类别，详见GoodsDetail
        for (ItemS item : itemsList) {
            GoodsDetail goods = GoodsDetail.newInstance(item.getIds(), item.getItem(), new Double(item.getPrice()).longValue(), item.getCount());
            // 创建好一个商品后添加至商品明细列表
            goodsDetailList.add(goods);
        }
        // 支付超时，线下扫码交易定义为5分钟
        String timeoutExpress = "5m";
        // 创建条码支付请求builder，设置请求参数
        AlipayTradePayRequestBuilder builder = new AlipayTradePayRequestBuilder()
                .setOutTradeNo(flowNo)
                .setSubject("爱玛客在线消费")
                .setAuthCode(authCode)
                .setTotalAmount(totalAmount)
                .setUndiscountableAmount("0.0")
                .setGoodsDetailList(goodsDetailList)
                .setTimeoutExpress(timeoutExpress);

        // 调用tradePay方法获取当面付应答
        AlipayF2FPayResult result = tradeService.tradePay(builder);

        switch (result.getTradeStatus()) {
            case SUCCESS:
                System.err.println("支付宝支付成功: )");
                model.addAttribute("result", "success");
                model.addAttribute("message", "支付宝支付成功");
                tradeAccountConsumptionFlow.setIsOver("1");
                insertInto(itemsList, tradeAccountConsumptionFlow, user, 1.0);
                tradeAccountConsumptionFlowService.updateById(tradeAccountConsumptionFlow);
                if (print && systemPrinter != null) {
                    //打印小票
                    orderReceiptPrint(itemsList, tradeAccountConsumptionFlow, response, systemPrinter);
                }
                break;
            case FAILED:
                System.err.println("支付宝支付失败!!!");
                System.err.println(result.getResponse().getBody());
                model.addAttribute("message", "支付宝支付失败!!!");
                break;
            case UNKNOWN:
                System.err.println("系统异常，订单状态未知!!!");
                model.addAttribute("message", "系统异常，订单状态未知!!!");
                break;
            default:
                System.err.println("不支持的交易状态，交易返回异常!!!");
                model.addAttribute("message", "不支持的交易状态，交易返回异常!!!");
                break;
        }
        return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
    }

    /**
     * 支付宝订单查询
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/alipayquery.do", method = RequestMethod.POST)
    public String alipayQuery(HttpServletResponse response, HttpServletRequest request) throws IOException {
        System.err.println("支付宝查询开始=====");
        Map<String, String> errMsg = new HashMap<>();
        String physicalCode = request.getParameter("physicalCode");
        String outTradeNo = flowNoMap.get(physicalCode) == null ? "" : flowNoMap.get(physicalCode);
        Map<String, String> map = new HashMap<>();
        List<TradeAccountConsumptionFlow> list = tradeAccountConsumptionFlowService.query()
                .eq("FLOW_NO", outTradeNo)
                .ge("CREATE_TIME", LocalDateTime.now().minusMinutes(2)).list();
        if (list.size() <= 0) {
            map.put("is_success", "NO");
            return JSONObject.toJSONString(map);
        }
        String payReason = request.getParameter("reason");
        if (StringUtils.isEmpty(payReason)) {
            payReason = "支付宝支付";
        }
        AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder()
                .setOutTradeNo(outTradeNo);
        // 调用tradePay方法获取当面付应答
        AlipayF2FQueryResult result = tradeService.queryTradeResult(builder);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                System.err.println("支付宝支付成功: )");
                map.put("is_success", "YES");
                LambdaUpdateWrapper<TradeAccountConsumptionFlow> flowLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                flowLambdaUpdateWrapper.set(TradeAccountConsumptionFlow::getReasonId, payReason)
                        .set(TradeAccountConsumptionFlow::getOrderStatus, 1)
                        .set(TradeAccountConsumptionFlow::getIsOver, 1)
                        .eq(TradeAccountConsumptionFlow::getFlowNo, outTradeNo);
                tradeAccountConsumptionFlowService.update(null, flowLambdaUpdateWrapper);
//                QueryWrapper<TradeConsumptionMain> tradeConsumptionMainQueryWrapper = new QueryWrapper<>();
//                tradeConsumptionMainQueryWrapper.eq("FLOW_NO",outTradeNo);
//                tradeConsumptionMainQueryWrapper.eq("ORDER_STATUS",0);
//                List<TradeConsumptionMain> tradeConsumptionMains = tradeConsumptionMainService.list(tradeConsumptionMainQueryWrapper);
//                LambdaUpdateWrapper<TradeConsumptionMain> mainLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
//                mainLambdaUpdateWrapper.set(TradeConsumptionMain::getReasonId,payReason).set(TradeConsumptionMain::getOrderStatus, 1).eq(TradeConsumptionMain::getFlowNo, outTradeNo);
//                tradeConsumptionMainService.update(null, mainLambdaUpdateWrapper);
//                LambdaUpdateWrapper<TradeConsumptionDetail> detailLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
//                detailLambdaUpdateWrapper.set(TradeConsumptionDetail::getReasonId,payReason).eq(TradeConsumptionDetail::getMainId, tradeConsumptionMains.get(0).getId());
//                tradeConsumptionDetailService.update(null, detailLambdaUpdateWrapper);
                break;
            case FAILED:
                System.err.println("支付宝支付失败!!!");
                map.put("is_success", "NO");
                break;
            case UNKNOWN:
                System.err.println("系统异常，订单状态未知!!!");
                errMsg.put("is_success", "交易异常,请确认刷卡是否成功!");
                return JSONObject.toJSONString(errMsg);
            default:
                System.err.println("不支持的交易状态，交易返回异常!!!");
                errMsg.put("is_success", "交易异常,请确认刷卡是否成功!");
                return JSONObject.toJSONString(errMsg);
        }
        return JSONObject.toJSONString(map);
    }

    /**
     * 微信支付
     *
     * @param data
     * @param model
     * @param request
     * @param response
     */
    @RequestMapping(value = "/money.do", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public String zhifu(@RequestBody JSONObject data, Model model, HttpServletResponse response, HttpServletRequest request) {

        model.addAttribute("result", "fail");
        SystemAclUser user = (SystemAclUser) WebUtils.getSessionAttribute(request, SessionNames.LOGIN_USER);
        System.err.println("微信支付开始=====");
        String totalFee;
        String authCode = data.getString("auth_code");
//        String tableNo = data.getString("tableNo");
        Boolean print = data.getObject("print", Boolean.class);//是否打印
        if (print == null) {
            print = printe;
        }
        if (!StringUtils.hasText(authCode)) {
            model.addAttribute("message", "支付码无效!!!");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }

        String totalAmount = data.getString("amount");
        String physicalCode = data.getString("physicalCode");
        SystemPosMachine systemPosMachine = systemPosMachineService.findByPhysicalCode(physicalCode);
        if (systemPosMachine == null) {
            model.addAttribute("result", "fail");
            model.addAttribute("message", "pos机不存在");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        systemPosMachine = autoMapper.mapperEntity(systemPosMachine);
        SystemPrinter systemPrinter = systemPosMachine.getReceiptPrinter();
        //清空上次订单
        flowNoMap.put(physicalCode, "");
        String canci = data.getString("canci");//餐次
        List<ItemS> itemsList = JSONObject.parseArray(data.getJSONArray("itemsList").toString(), ItemS.class);
        //生成消费流水
        TradeAccountConsumptionFlow tradeAccountConsumptionFlow = new TradeAccountConsumptionFlow();
        tradeAccountConsumptionFlow.setQuantity(itemsList.stream().mapToDouble(ItemS::getCount).sum());
        tradeAccountConsumptionFlow.setStickerPrinter(systemPosMachine.getStickerPrinter());
        ConfigMealTime configMealTime = configMealTimeService.findByName(canci);
        tradeAccountConsumptionFlow.setRestaurantId(systemPosMachine.getRestaurantId());
        tradeAccountConsumptionFlow.setPosMachineId(systemPosMachine.getId());
        if (configMealTime != null) {
            tradeAccountConsumptionFlow.setMealTimeId(configMealTime.getId());
        }
        tradeAccountConsumptionFlow.setOperateType(0);
        tradeAccountConsumptionFlow.setSettlementTypeId(SETTLEMENT_TYPE_ID_jiesuan);

        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyMMddHHmmss");
        tradeAccountConsumptionFlow.setFlowNo(PROJECT_CODE + "-XF" + df.format(LocalDateTime.now()) + UUID.randomUUID().toString().substring(0, 4));
        //记录订单号
        flowNoMap.put(physicalCode, tradeAccountConsumptionFlow.getFlowNo());
        log.info(tradeAccountConsumptionFlow.getFlowNo());
        tradeAccountConsumptionFlow.setIsPay("0");
        tradeAccountConsumptionFlow.setTableNo(new Double(Math.random() * 900000 + 100000).intValue() + "");
        tradeAccountConsumptionFlow.setCreatorId(user.getId());
        tradeAccountConsumptionFlow.setCreatorName(user.getName());
        tradeAccountConsumptionFlow.setBeforeAmount(new BigDecimal(0));
        tradeAccountConsumptionFlow.setActualAmount(Double.valueOf(totalAmount));
        tradeAccountConsumptionFlow.setAfterAmount(new BigDecimal(0));
        tradeAccountConsumptionFlow.setReasonId("微信支付");
        tradeAccountConsumptionFlow.setCreateTime(LocalDateTime.now());
        tradeAccountConsumptionFlow.setIsOver("0");//未支付
        //存储流水
        tradeAccountConsumptionFlowService.save(tradeAccountConsumptionFlow);

        HashMap<String, String> map = new HashMap<>();
        try {
            Float f = Float.parseFloat(totalAmount) * 100;
            totalFee = String.valueOf(f).substring(0, f.toString().indexOf('.'));
            System.err.println("totalFee------" + totalFee);
            map.put("total_fee", totalFee);
        } catch (Exception e) {
            totalFee = "0";
        }
        map.put("spbill_create_ip", "123.12.12.123");
        map.put("auth_code", authCode.trim());
        map.put("out_trade_no", tradeAccountConsumptionFlow.getFlowNo());
        map.put("body", "爱玛客在线消费");
        try {
            WXPayConfigImpl config = WXPayConfigImpl.getInstance();
            System.err.println("WX--------------1");
            WXPay wxpay = new WXPay(config);
            System.err.println("WX--------------2");
            Map<String, String> microPay = wxpay.microPay(map);
            System.err.println("WX----3-----microPsy" + microPay.toString());
            // 判断是否成功
            Map<String, String> ResultMap = isSuccess(microPay, wxpay, map);
            System.err.println("map中issuccess值 ；" + ResultMap.get("is_success"));
            int i = 0;
            // 判断是否需要调取订单信息
            while (i <= 5 && ResultMap.get("is_success") != null) {
                System.err.println(i + "次" + ResultMap.get("is_success") + ResultMap);
                if ("YES".equals(ResultMap.get("is_success"))) {
                    model.addAttribute("result", "success");
                    model.addAttribute("message", "微信支付成功");
                    tradeAccountConsumptionFlow.setIsOver("1");
                    insertInto(itemsList, tradeAccountConsumptionFlow, user, 1.0);
                    tradeAccountConsumptionFlowService.updateById(tradeAccountConsumptionFlow);
                    if (print && systemPrinter != null) {
                        //打印小票
                        orderReceiptPrint(itemsList, tradeAccountConsumptionFlow, response, systemPrinter);
                    }
                    break;
                } else if ("NO".equals(ResultMap.get("is_success"))) {
                    model.addAttribute("message", "支付失败");
                    return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
                }
                Thread.sleep(5000);
                map.remove("auth_code");
                Map<String, String> againData = new HashMap<>();
                againData.put("appid", map.get("appid"));
                againData.put("mch_id", map.get("mch_id"));
                againData.put("out_trade_no", map.get("out_trade_no"));
                againData.put("nonce_str", map.get("nonce_str"));
                againData.put("sign", map.get("sign"));
                ResultMap = wxpay.orderQuery(againData);
                System.err.println("再次map" + ResultMap);
                ResultMap = isSuccess(ResultMap, wxpay, map);
                i++;
            }
            if (i == 6) {
                Map<String, String> reverseMap = new HashMap<>();
                reverseMap.put("appid", map.get("appid"));
                reverseMap.put("mch_id", map.get("mch_id"));
                reverseMap.put("out_trade_no", map.get("out_trade_no"));
                reverseMap.put("nonce_str", map.get("nonce_str"));
                reverseMap.put("sign", map.get("sign"));
                Map<String, String> reverse = wxpay.reverse(reverseMap);
                if ("SUCCESS".equals(reverse.get("result_code")) && "SUCCESS".equals(reverse.get("return_code"))) {
                    System.err.println("订单已取消");
                    model.addAttribute("message", "订单已取消!!!");
                    return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
                }
            }
            System.err.println("结果===============" + ResultMap);
        } catch (Exception e) {
            e.printStackTrace();
            model.addAttribute("message", "交易异常!!!");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
    }

    /**
     * 微信订单查询
     *
     * @param request
     * @param response
     */
    @RequestMapping(value = "/wxpayQuery.do", method = RequestMethod.POST)
    public String wxpayQuery(Model model, HttpServletResponse response, HttpServletRequest request) {
        model.addAttribute("result", "fail");
        String physicalCode = request.getParameter("physicalCode");
        String outTradeNo = flowNoMap.get(physicalCode) == null ? "" : flowNoMap.get(physicalCode);
        HashMap<String, String> map = new HashMap<>();
        List<TradeAccountConsumptionFlow> list = tradeAccountConsumptionFlowService.query()
                .eq("FLOW_NO", outTradeNo)
                .ge("CREATE_TIME", LocalDateTime.now().minusMinutes(2)).list();
        if (list.size() <= 0) {
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        WXPayConfigImpl config = null;
        try {
            config = WXPayConfigImpl.getInstance();
            WXPay wxpay = new WXPay(config);
            map.put("out_trade_no", outTradeNo);
            Map<String, String> ResultMap = wxpay.orderQuery(map);
            ResultMap = isSuccess(ResultMap, wxpay, map);
            int i = 0;
            while (i <= 5 && ResultMap.get("is_success") != null) {
                System.err.println(i + "次" + ResultMap.get("is_success") + ResultMap);
                if ("YES".equals(ResultMap.get("is_success"))) {
                    model.addAttribute("result", "success");
                    model.addAttribute("message", "订单已支付");
                    LambdaUpdateWrapper<TradeAccountConsumptionFlow> flowLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
                    flowLambdaUpdateWrapper.set(TradeAccountConsumptionFlow::getOrderStatus, 1)
                            .set(TradeAccountConsumptionFlow::getIsOver, 1)
                            .eq(TradeAccountConsumptionFlow::getFlowNo, outTradeNo);
                    tradeAccountConsumptionFlowService.update(null, flowLambdaUpdateWrapper);
                    break;
                } else if ("NO".equals(ResultMap.get("is_success"))) {
                    model.addAttribute("message", "支付失败");
                    return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
                }
                Thread.sleep(5000);
                map.remove("auth_code");
                Map<String, String> againData = new HashMap<>();
                againData.put("appid", map.get("appid"));
                againData.put("mch_id", map.get("mch_id"));
                againData.put("out_trade_no", map.get("out_trade_no"));
                againData.put("nonce_str", map.get("nonce_str"));
                againData.put("sign", map.get("sign"));
                ResultMap = wxpay.orderQuery(againData);
                System.err.println("再次map" + ResultMap);
                ResultMap = isSuccess(ResultMap, wxpay, map);
                i++;
            }
            if (i == 6) {
                Map<String, String> reverseMap = new HashMap<>();
                reverseMap.put("appid", map.get("appid"));
                reverseMap.put("mch_id", map.get("mch_id"));
                reverseMap.put("out_trade_no", map.get("out_trade_no"));
                reverseMap.put("nonce_str", map.get("nonce_str"));
                reverseMap.put("sign", map.get("sign"));
                Map<String, String> reverse = wxpay.reverse(reverseMap);
                if (reverse.get("result_code").equals("SUCCESS") && reverse.get("return_code").equals("SUCCESS")) {
                    System.err.println("订单已取消");
                    model.addAttribute("message", "订单已取消!!!");
                    return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            model.addAttribute("message", "交易异常!!!");
            return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);
        }
        return JSONObject.toJSONString(model, SerializerFeature.IgnoreNonFieldGetter);

    }


    private Map<String, String> isSuccess(Map<String, String> map, WXPay wxpay, Map<String, String> data) {
        if ("SUCCESS".equals(map.get("return_code"))) {// 通讯成功
            if ("SUCCESS".equals(map.get("result_code"))) {// 交易成功
                if (map.get("trade_state") == null) {
                    map.put("is_success", "YES");
                    System.err.println("111 ===" + map.get("is_success"));
                } else if ("USERPAYING".equals(map.get("trade_state"))) {
                    map.put("is_success", "UNKNOWN");
                    System.err.println("222 ===" + map.get("is_success"));
                } else if ("SUCCESS".equals(map.get("trade_state"))) {
                    map.put("is_success", "YES");
                    System.err.println("333 ===" + map.get("is_success"));
                }
                return map;
            } else if ("FAIL".equals(map.get("result_code"))) {
                String errCode = map.get("err_code");// 交易不明确,查询订单
                if ("USERPAYING".equals(errCode) || "BANKERROR".equals(errCode) || "SYSTEMERROR".equals(errCode)) {
                    map.put("is_success", "SEARCH");
                    System.err.println("444 ===unKnown");
                    return map;
                }
            }
            System.err.println("555 ===FAIL");
            map.put("is_success", "NO");
            return map;
        } else {
            System.err.println("支付失败，请重新扫码! 666===FAIL");
            map.put("is_success", "NO");
            return map;
        }
    }

    private void insertInto(List<ItemS> itemsList, TradeAccountConsumptionFlow tradeAccountConsumptionFlow, SystemAclUser user, Double payoutRatio) {
        List<TradeConsumptionDetail> detailList = new ArrayList<>();
        TradeConsumptionMain tradeConsumptionMain = new TradeConsumptionMain();
        tradeConsumptionMain.setCustomerId(tradeAccountConsumptionFlow.getCustomerId());
        tradeConsumptionMain.setRestaurantId(tradeAccountConsumptionFlow.getRestaurantId());
        tradeConsumptionMain.setMealTimeId(tradeAccountConsumptionFlow.getMealTimeId());
        tradeConsumptionMain.setPosMachineId(tradeAccountConsumptionFlow.getPosMachineId());
        tradeConsumptionMain.setFlowNo(tradeAccountConsumptionFlow.getFlowNo());
        tradeConsumptionMain.setConsumptionTime(LocalDateTime.now());
        tradeConsumptionMain.setOrderType(0);
        tradeConsumptionMain.setXmlOut("0");
        tradeConsumptionMain.setTableNo(tradeAccountConsumptionFlow.getTableNo());
//        double count = 0;
//        double money = 0.0;
//        for (ItemS items : itemsList) {
//            count += items.getCount();
//        }
        tradeConsumptionMain.setQuantity(tradeAccountConsumptionFlow.getQuantity());
        tradeConsumptionMain.setShouldPaidAmount(tradeAccountConsumptionFlow.getActualAmount() + tradeAccountConsumptionFlow.getDiscountAmount());
        tradeConsumptionMain.setActualAmount(tradeAccountConsumptionFlow.getActualAmount());
        tradeConsumptionMain.setDiscountPercent(BigDecimal.ZERO);
        tradeConsumptionMain.setDiscountAmount(tradeAccountConsumptionFlow.getDiscountAmount());
        tradeConsumptionMain.setReasonId(tradeAccountConsumptionFlow.getReasonId());
        tradeConsumptionMain.setQuotaPrice(BigDecimal.ZERO);
        tradeConsumptionMain.setTimes(0);
        tradeConsumptionMain.setIsSettlement("1");
        tradeConsumptionMain.setCreatorId(user.getId());
        tradeConsumptionMain.setCreatorName(user.getName());
        tradeConsumptionMain.setCreateTime(LocalDateTime.now());
        tradeConsumptionMain.setCustomerName(tradeAccountConsumptionFlow.getCustomerName());
        tradeConsumptionMain.setAccountId(tradeAccountConsumptionFlow.getAccountId());
        tradeConsumptionMainService.save(tradeConsumptionMain);
        if (tradeConsumptionMain.getDiscountAmount() > 0) {
            MemberAllowanceUseHistory memberAllowanceUseHistory = memberAllowanceUseHistoryService.query().eq("member_id", tradeConsumptionMain.getCustomerId())
                    .eq("use_time", tradeConsumptionMain.getConsumptionTime().toLocalDate())
                    .eq("meal_code", tradeAccountConsumptionFlow.getMealCode()).one();
            if (memberAllowanceUseHistory == null) {
                memberAllowanceUseHistory = new MemberAllowanceUseHistory();
                memberAllowanceUseHistory.setMemberId(tradeConsumptionMain.getCustomerId());
                memberAllowanceUseHistory.setMealCode(tradeAccountConsumptionFlow.getMealCode());
                memberAllowanceUseHistory.setUseTime(LocalDate.now());
                memberAllowanceUseHistory.setCreateTime(LocalDateTime.now());
                memberAllowanceUseHistory.setOrderId(tradeConsumptionMain.getId());
                memberAllowanceUseHistory.setAllowanceAmount(tradeAccountConsumptionFlow.getMaxAllowance() - tradeAccountConsumptionFlow.getDiscountAmount());
                memberAllowanceUseHistoryService.save(memberAllowanceUseHistory);
            } else {
                memberAllowanceUseHistory.setAllowanceAmount(memberAllowanceUseHistory.getAllowanceAmount() - tradeConsumptionMain.getDiscountAmount());
                memberAllowanceUseHistory.setCreateTime(LocalDateTime.now());
                memberAllowanceUseHistoryService.updateById(memberAllowanceUseHistory);
            }
        }
        Double discountAmount = tradeConsumptionMain.getDiscountAmount();
        String remarks = "";
        for (ItemS itemS : itemsList) {
            if (StringUtils.hasText(itemS.getRemark())) {
                remarks += itemS.getItem() + ":" + itemS.getRemark() + "\r\n";
            }
            TradeConsumptionDetail tradeConsumptionDetail = new TradeConsumptionDetail();
            tradeConsumptionDetail.setMainId(tradeConsumptionMain.getId());
            tradeConsumptionDetail.setQuantity(itemS.getCount() * payoutRatio);
//            tradeConsumptionDetail.setHandDiscount(BigDecimal.ZERO);
            tradeConsumptionDetail.setReasonId(tradeAccountConsumptionFlow.getReasonId());
            tradeConsumptionDetail.setActualAmount(new BigDecimal(itemS.getCount() * itemS.getPrice()));
            if (discountAmount >= tradeConsumptionDetail.getActualAmount().doubleValue()) {
                tradeConsumptionDetail.setHandDiscount(tradeConsumptionDetail.getActualAmount());
                discountAmount -= tradeConsumptionDetail.getActualAmount().doubleValue();
                // 实际总额(打折后)
                tradeConsumptionDetail.setActualAmount(BigDecimal.ZERO);
            } else if (discountAmount > 0) {
                tradeConsumptionDetail.setHandDiscount(new BigDecimal(discountAmount));
                tradeConsumptionDetail.setActualAmount(new BigDecimal(tradeConsumptionDetail.getActualAmount().doubleValue() - discountAmount));
                discountAmount = 0.0;
            } else {
                tradeConsumptionDetail.setHandDiscount(BigDecimal.ZERO);
            }
            tradeConsumptionDetail.setMainId(tradeConsumptionMain.getId());
            tradeConsumptionDetail.setPrice(new BigDecimal(itemS.getPrice()));
            tradeConsumptionDetail.setFoodId(itemS.getIds());
            QueryWrapper<MenuFoodPrice> menuFoodPriceWrapper = new QueryWrapper<>();
            menuFoodPriceWrapper.eq("FOOD_ID", itemS.getIds());
            menuFoodPriceWrapper.and(i -> i.eq("MEAL_TIME_ID", tradeAccountConsumptionFlow.getMealTimeId()).or().eq("MEAL_TIME_ID", MEAL_TIME_ID_quantian));
            menuFoodPriceWrapper.le("START_TIME", LocalDateTime.now());
            menuFoodPriceWrapper.ge("END_TIME", LocalDateTime.now());
            MenuFoodPrice menuFoodPrice = menuFoodPriceService.getOne(menuFoodPriceWrapper, false);
            if (menuFoodPrice != null) {
                tradeConsumptionDetail.setBusinessTypeId(menuFoodPrice.getBusinessTypeId());
//                tradeConsumptionDetail.setFoodId(menuFoodPrice.getFoodId());
            }
            detailList.add(tradeConsumptionDetail);
        }
        tradeConsumptionMain.setRemarks(remarks);
        tradeConsumptionMainService.updateById(tradeConsumptionMain);
        tradeConsumptionDetailService.saveBatch(detailList);
        if (cupPrinte && payoutRatio == 1.0 && tradeAccountConsumptionFlow.getStickerPrinter() != null) {
            smallTicketPrinter.cupStickersPrint(itemsList, tradeAccountConsumptionFlow);
        }
    }


    // 调用打印机接口
    private void orderReceiptPrint(List<ItemS> itemsList, TradeAccountConsumptionFlow tradeAccountConsumptionFlow, HttpServletResponse response, SystemPrinter systemPrinter) {
        try {
//            String data = smallTicketPrinter.queryPrinterStatus(systemPrinter.getSn());
            String s = smallTicketPrinter.printOrder(itemsList, tradeAccountConsumptionFlow, systemPrinter);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
